﻿//#define DEBUG

using System;
using System.Linq;
using CommonBehaviors.Actions;
using FarmerJoe.Helpers;
using FarmerJoe.Helpers.Logging;
using FarmerJoe.Helpers.Units;
using FarmerJoe.Settings;
using Styx;
using Styx.CommonBot;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Action = Styx.TreeSharp.Action;

namespace FarmerJoe.Classes
{
    public static partial class Hunter
    {
        public static Composite CombatBehavior_Beast
        {
            get
            {
                return new PrioritySelector(

                    new Decorator(ret=> Me.InVehicle, new ActionAlwaysSucceed()),

                    Spells.WaitForCast(),
                    Misc.EnsureTarget(),

                    SummonPet(FpswareSettings.Instance.Hunter.PetSlot),
                    PetSpells(),
                   
                    // Trap, Wyvery Sting and Scatter Shot
                    CrowdControl(),
                    Movement.ForceFacingTarget(),


                    Pets.DefendMe(),

                    // Break free from the shackles of our oppressors
                    Spells.Cast("Master's Call", ret=> Me.GotAlivePet && CLC.ResultOK(FpswareSettings.Instance.Hunter.MastersCall) && Me.Auras.Any(a=> a.Value.Spell.Mechanic == WoWSpellMechanic.Incapacitated || a.Value.Spell.Mechanic == WoWSpellMechanic.Rooted || a.Value.Spell.Mechanic == WoWSpellMechanic.Sapped || a.Value.Spell.Mechanic == WoWSpellMechanic.Snared || a.Value.Spell.Mechanic == WoWSpellMechanic.Stunned|| a.Value.Spell.Mechanic == WoWSpellMechanic.Asleep),ret=> Me),
                    Spells.Cast("Bestial Wrath", ret => Me.GotAlivePet && Me.Auras.Any(a => a.Value.Spell.Mechanic == WoWSpellMechanic.Polymorphed || a.Value.Spell.Mechanic == WoWSpellMechanic.Fleeing || a.Value.Spell.Mechanic == WoWSpellMechanic.Sapped)),


                    // Somehow we've got a target that is not hostile or attackable. Blacklist it and move on
                    new Decorator(ret => !CT.Attackable || CT.IsFriendly,
                        new Sequence(
                            new Action(context => Log.Write(Colours.InformativeColour,"Somehow we've got a target that is friendly or not attackable, blacklisting it and moving on.")),
                            new Action(context => Blacklist.Add(CT, TimeSpan.FromMinutes(1))),
                            new Action(context => Me.ClearTarget())
                        )),


                    // Auto attack, ensure we're shooting
                    new Decorator(ret => !StyxWoW.Me.IsAutoAttacking && StyxWoW.Me.AutoRepeatingSpellId != 75,
                        new Action(delegate { Lua.DoString("StartAttack()"); return RunStatus.Failure; })),
                    // Healing
                    Common.UseHealthManaRegenAgent(ClassParser.HealthPotion, 0),
                    Spells.Buff("Mend Pet",ret=> Me.Pet, ret=> Me.GotAlivePet && Me.Pet.HealthPercent < FpswareSettings.Instance.Hunter.MindPetHealth && !Me.Pet.HasAura("Mend Pet") && Me.Pet.InLineOfSpellSight && Timers.AutoExpire("Mend Pet",1000),false),
                    Spells.BuffSelf("Exhilaration", ret => Me.GotAlivePet && Me.Pet.HealthPercent < FpswareSettings.Instance.Hunter.ExhilarationPetHealth),
                    Spells.BuffSelf("Exhilaration", ret => Me.HealthPercent < FpswareSettings.Instance.Hunter.ExhilarationHealth && SpellManager.Cast("Exhilaration") &&Timers.AutoExpire("Exhilaration",3000)),
                    
                    Inventory.UseTrinket1(),
                    Inventory.UseTrinket2(),
                    Movement.MoveToLOS(),
                    Movement.FaceTarget(),
                    Movement.Fixes(),

                    Spells.Cast("Aspect of the Hawk", ret => !InAotH),
                    //Spells.Cast("Kill Shot", ret => CT.HealthPercent <= 20),

                    // Kill Shot! (with Stop casting)
                    Spells.Cast("Kill Shot"),
                    new Decorator(ret=> CT.HealthPercent <= 20 && SpellManager.HasSpell("Kill Shot") && !SpellManager.Spells["Kill Shot"].Cooldown,
                        new Sequence(
                            new DecoratorContinue(ret => Me.IsCasting && Timers.AutoExpire("Kill Shot Message",3000),
                                new Sequence(
                                    new Action(context => Log.Write(Colours.InformativeColour,"Stop Casting! So we can cast Kill Shot")),
                                    new Action(context => SpellManager.StopCasting()),
                                    new WaitContinue(1, ret => !SpellManager.GlobalCooldown, new ActionAlwaysSucceed())
                                    )),
                            
                            Spells.Cast("Kill Shot")
                        )
                    ),

                    
                    new Decorator(ret=> !FpswareSettings.Instance.Hunter.Disengage.Contains("never"),
                        new PrioritySelector(
                            Spells.Cast("Disengage", ret => Battlegrounds.IsInsideBattleground && /*AddsAndOthers.IsAnyPlayerTargetingMe && */AddsAndOthers.HasHostilePlayersInRange(8) && CanNavigateBehindMe),
                            Spells.Cast("Disengage", ret => FpswareSettings.Instance.Hunter.Disengage.Contains("always") && !Battlegrounds.IsInsideBattleground && CT.IsWithinMeleeRange && CanNavigateBehindMe)
                            )    
                    ),
                    



                    // Feign Death
                    new Decorator(ret => !Battlegrounds.IsInsideBattleground && Me.HealthPercent < FpswareSettings.Instance.Hunter.FeignDeathHealth && SpellManager.CanCast("Feign Death") && AddsAndOthers.IsAnyPVETargetingMe,
                        new Sequence(
                            new Action(context => Log.Write(Colours.InformativeColour,"OMG we're about to die .... Feign Death!")),
                            
                            // But first disengage 
                            new DecoratorContinue(ret=> FpswareSettings.Instance.Hunter.FeignDeathDisengage.Contains("always") && SpellManager.CanCast("Disengage") && CanNavigateBehindMe,
                                new PrioritySelector(
                                    new Action(context => Log.Write(Colours.InformativeColour, "... but first Disengage")),
                                    new Action(context => SpellManager.Cast("Disengage")),
                                    new WaitContinue(3, ret => false, new ActionAlwaysSucceed())
                                )
                            ),
                            
                            Spells.Cast("Feign Death", ret=>  Me.HealthPercent < FpswareSettings.Instance.Hunter.FeignDeathHealth && AddsAndOthers.IsAnyPVETargetingMe),
                            //new Action(context => SpellManager.Cast("Feigh Death")),
                            new WaitContinue(2, ret => false, new ActionAlwaysSucceed())
                            )),

                    Spells.Cast("Widow Venom", ret => CLC.ResultOK(FpswareSettings.Instance.Hunter.WidowVenom) && !CT.HasMyAura("Widow Venom") && !Me.IsCasting && Timers.AutoExpire("Widow Venom",3000)),
                    Spells.BuffSelf("Deterrence",ret=> Me.HealthPercent < FpswareSettings.Instance.Hunter.DeterrenceHealth),
                    

                    // Glyph of Distracting Shot. Its like a misdirect onto your pet.
                    new Decorator(ret => AddsAndOthers.HasAdds && !Battlegrounds.IsInsideBattleground && TalentsAndGlyphs.HasGlyph("Distracting Shot") && SpellManager.HasSpell("Distracting Shot") && CLC.ResultOK(FpswareSettings.Instance.Hunter.DistractingShot) && !SpellManager.Spells["Distracting Shot"].Cooldown && MobToDistractGlyphed != null,// && SpellManager.CanCast("Distracting Shot"),
                        new Sequence(
                            new WaitContinue(2, ret => !SpellManager.GlobalCooldown && !Me.IsCasting, new ActionAlwaysSucceed()),
                            new Action(context => Log.Write(Colours.InformativeColour, "Distracting Shot on add! You're glyphed for it")),
                            new Action(context => MobToDistractGlyphed.Face()),
                            new WaitContinue(1, ret => false, new ActionAlwaysSucceed()),
                            Spells.Buff("Distracting Shot", ret => MobToDistractGlyphed, ret => SpellManager.CanCast("Distracting Shot"), false)
                            )),
                    
                    HuntersMark(),

                    // Traps
                    /*
                    new Decorator(ret => Me.HasAura("Trap Launcher") && SpellManager.HasSpell("Explosive Trap") && !SpellManager.Spells["Explosive Trap"].Cooldown && CT.Distance < 40 && !CT.IsMoving && !CT.IsCrowdControlledUnitNearTarget(10) && (CT.HealthPercent > 80 || AddsAndOthers.HasAdds) && Timers.AutoExpire("Trap Spam",3000),// && BestExplosiveTrapTarget != null,
                        new Sequence(
                            new Action(ret => Log.Write(Colours.InformativeColour,"Explosive Trap")),
                            new Action(ret => SpellManager.Cast("Explosive Trap")),
                            new WaitContinue(1, ret => Me.HasPendingSpell("Explosive Trap"), new ActionAlwaysSucceed()),
                            new Action(ret => SpellManager.ClickRemoteLocation(CT.Location)),
                            new WaitContinue(1, ret => false, new ActionAlwaysSucceed())
                            )
                        ),
                     */



                    Spells.Cast("Powershot", ret => Me.FocusPercent > 20 && CT.HealthPercent > FpswareSettings.Instance.Hunter.PowershotHealth && !FpswareSettings.Instance.Hunter.Powershot.Contains("never")),
                    Spells.Cast("Bestial Wrath", ret => CLC.ResultOK(FpswareSettings.Instance.Hunter.BestialWrath)),
                    Spells.Cast("Dire Beast", ret => CLC.ResultOK(FpswareSettings.Instance.Hunter.DireBeast)),
                    Spells.Cast("Stampede", ret => CLC.ResultOK(FpswareSettings.Instance.Hunter.Stampede)),
                    Spells.BuffSelf("Readiness", ret=> SpellManager.HasSpell("Exhilaration") && SpellManager.Spells["Exhilaration"].Cooldown && FpswareSettings.Instance.Hunter.ReadinessExhilaration.Contains("always")),
                    Spells.BuffSelf("Readiness", ret => SpellManager.HasSpell("Rapid Fire") && SpellManager.Spells["Rapid Fire"].Cooldown  && FpswareSettings.Instance.Hunter.ReadinessRapidFire.Contains("always")),
                    Spells.Cast("Silencing Shot", ret=> Me.GotTarget && CT.IsCasting && CLC.ResultOK(FpswareSettings.Instance.Hunter.SilencingShot) && CT.CastingSpell.CastTime > 1),
                    Spells.Cast("Blink Strike", ret => Me.GotAlivePet && Me.Pet.GotTarget && CLC.ResultOK(FpswareSettings.Instance.Hunter.BlinkStrike) && Me.Pet.Location.Distance(CT.Location) <= 40),
                    //Spells.Cast("Powershot", ret=> CT.HealthPercent > FpswareSettings.Instance.Hunter.PowerShotMinTargetHealth && !FpswareSettings.Instance.Hunter.Powershot.Contains("never")),
                    Spells.Cast("Intimidation", ret => Me.GotAlivePet && Me.Pet.GotTarget && (CLC.ResultOK(FpswareSettings.Instance.Hunter.Intimidation) || CT.IsPlayer || CT.CurrentTargetGuid == Me.Guid) && Me.Pet.Location.Distance(CT.Location) <= Spells.MeleeRange),
                    Spells.Cast("Concussive Shot", ret => FpswareSettings.Instance.Hunter.ConcussiveShot.Contains("approach") && CT.IsApproachingMe()  && CT.Distance > 15),
                    Spells.Cast("Concussive Shot", ret => (CT.IsPlayer || FpswareSettings.Instance.Hunter.ConcussiveShot.Contains("always")) && CT.Distance > 10 && CT.IsMoving && CT.AuraTimeLeft("Concussive Shot") < 3),
                    Spells.Cast("Rapid Fire", ret => CLC.ResultOK(FpswareSettings.Instance.Hunter.RapidFire) && !Me.HasAura("Rapid Fire")),
                    Spells.Cast("Kill Command", ret=> Me.GotAlivePet && CLC.ResultOK(FpswareSettings.Instance.Hunter.KillCommand) && Me.Pet.GotTarget && Me.Pet.Location.Distance(CT.Location) <= 40),
                    // Just make sure we're casting this instead of running out of Focus
                    //Spells.Cast("Steady Shot", ret=> Me.FocusPercent < 25),
                    
                    // DoT Adds
                    new Decorator(ret => AddsAndOthers.HasAdds && CLC.ResultOK(FpswareSettings.Instance.Hunter.SerpentSting) && CLC.ResultOK(FpswareSettings.Instance.Hunter.SerpentStingAdds)&& !Me.IsCasting && DoTAddTarget("Serpent Sting", true) != null,
                        new Sequence(
                            Spells.Buff("Serpent Sting", ret => DoTAddTarget("Serpent Sting", true), ret => SpellManager.CanCast("Serpent Sting"), true),
                            new Action(context => Log.Write(Colours.InformativeColour, "Dotting add with Serpent Sting")),
                            new WaitContinue(1, ret => !SpellManager.GlobalCooldown, new ActionAlwaysSucceed())
                        )
                    ),

                    // Serpent Sting
                    new Decorator(ret => CT.AuraTimeLeft("Serpent Sting") < 3 && CLC.ResultOK(FpswareSettings.Instance.Hunter.SerpentSting),
                        new PrioritySelector(
                            new Decorator(ret=> CT.Elite,
                                Spells.Cast("Serpent Sting")),

                            new Decorator(ret => !CT.Elite && CT.HealthPercent > FpswareSettings.Instance.Hunter.SerpentStingMinHealth,
                                Spells.Cast("Serpent Sting"))
                        )
                    ),

                    Spells.Cast("Glaive Toss", ret => !CT.IsCrowdControlledUnitNearTarget(10) && Me.FocusPercent > 30 && CLC.ResultOK(FpswareSettings.Instance.Hunter.GlaiveToss)),
                    //Spells.Cast("Serpent Sting", ret => CT.AuraTimeLeft("Serpent Sting") < 3 && (CT.HealthPercent > 45 && !CT.Elite)  && Timers.AutoExpire("Serpent Sting",1500)),
                    Spells.BuffSelf("Focus Fire", ret => Me.HasAura("Frenzy") && Me.GotAlivePet && !Me.HasAura("Focus Fire") && Me.Auras["Frenzy"].StackCount >= Convert.ToInt32(FpswareSettings.Instance.Hunter.FocusFire) && !SpellManager.GlobalCooldown),
                    Spells.Cast("Multi-Shot", ret => CLC.ResultOK(FpswareSettings.Instance.Hunter.MultiShot) && !CT.IsCrowdControlledUnitNearTarget(8) && (Me.FocusPercent > 50 || Me.HasAura("The Beast Within"))),
                    Spells.Cast("Arcane Shot", ret => Me.ActiveAuras.ContainsKey("Thrill of the Hunt")),
                    Spells.Cast("Arcane Shot", ret => Me.FocusPercent > FpswareSettings.Instance.Hunter.BeastArcaneShotFocus || Me.ActiveAuras.ContainsKey("The Beast Within")),
                    Spells.Cast("Steady Shot", ret=> !SpellManager.CanCast("Kill Shot")),

                    new Decorator(ret => Me.IsCasting || Me.IsChanneling, new Action(context => RunStatus.Success)),

                    Movement.MoveToTarget(true, 36f),

                    new Decorator(ret=> Me.Combat, new ActionAlwaysSucceed())
                    );
            }
        }

        public static Composite PullBehavior_Beast
        {

            get
            {
                
                if (!Timers.Exists("Pet Attack Pull")) Timers.Add("Pet Attack Pull");

                return new PrioritySelector(

                    new Decorator(ret => Me.InVehicle, new ActionAlwaysSucceed()),
                    Spells.WaitForCast(),
                    SummonPet(FpswareSettings.Instance.Hunter.PetSlot),
                    Misc.EnsureTarget(),
                    Movement.MoveToLOS(),
                    Movement.FaceTarget(),
                    Movement.Fixes(),
                    new Sequence(ret => Me.Mounted, new Action(ret => Spells.Dismount("Pulling")), new Action(ctx => RunStatus.Failure)),

                    // Non hostile target?
                    new Decorator(ret => !CT.Attackable || CT.IsFriendly,
                        new Sequence(
                            new Action(context => Log.Write(Colours.InformativeColour, "Somehow we've got a target that is friendly or not attackable, blacklisting it and moving on.")),
                            new Action(context => Blacklist.Add(CT, TimeSpan.FromMinutes(1))),
                            new Action(context => Me.ClearTarget())
                        )),

                    new Decorator(ret => Me.GotAlivePet && CT.IsAlive && Timers.Expired("Pet Attack Pull", 2000) && ((Me.Pet.GotTarget && Me.Pet.CurrentTargetGuid != Me.CurrentTargetGuid) || !Me.Pet.GotTarget),
                        new Sequence(
                            new Action(delegate { Pets.CastPetAction("Attack"); }),
                            new Action(delegate { Timers.Reset("Pet Attack Pull"); }),
                            new Action(ctx => RunStatus.Failure)
                            )),

                    HuntersMark(),

                    new Decorator(ret => FpswareSettings.Instance.Hunter.BeastMasteryPull.Contains("user defined"),
                                  new PrioritySelector(
                                      )),


                    new Decorator(ret => FpswareSettings.Instance.Hunter.BeastMasteryPull.Contains("automatic"),
                                  new PrioritySelector(

                                        Spells.Cast("Aspect of the Hawk", ret => !InAotH),

                                        new Decorator(ret=> Me.GotTarget && !Me.CurrentTarget.Attackable,
                                            new Sequence(
                                                new Action(context => Blacklist.Add(CT, TimeSpan.FromMinutes(3))),
                                                new Action(context => Me.ClearTarget())
                                                )),

                                        HuntersMark(),

                                        Spells.Cast("Hunter's Mark", ret => !CT.HasAura("Hunter's Mark") && CLC.ResultOK(FpswareSettings.Instance.Hunter.HuntersMark) && !TalentsAndGlyphs.HasGlyph("Marked for Death")),
                                        Spells.Cast("Blink Strike", ret => Me.GotAlivePet && CT.Distance <= 40 && Timers.AutoExpire("Blink Strike",1000)),
                                        Spells.Cast("Powershot", ret => Me.FocusPercent > 20),
                                        Spells.Cast("Barrage", ret => Me.FocusPercent > 30),
                                        //Spells.Buff("Misdirection", ret=> Me.Pet, ret => Me.GotAlivePet && SpellManager.HasSpell("Blink Strike") && SpellManager.Spells["Blink Strike"].Cooldown,false),
                                        Spells.Buff("Misdirection", ret => Me.Pet, ret => Me.GotAlivePet && !CT.IsPlayer && !Me.HasAura("Misdirection"), false),
                                        Spells.Cast("Steady Shot", ret => Me.FocusPercent < 25),
                                        Spells.Cast("Arcane Shot", ret=> Me.CurrentFocus > 20),
                                        Spells.Cast("Serpent String", ret => !CT.HasMyAura("Serpent String"))
                                        

                                      )),


                    new Decorator(ret => Me.IsCasting || Me.IsChanneling, new Action(context => RunStatus.Success)),
                    Movement.PullApproach(),
                    Movement.MoveToTarget(true, 35f)
                    );
            }
        }

    }
}